package ph.com.gs3.formalistics.service.services;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import ph.com.gs3.formalistics.global.utilities.logging.FLLogger;
import ph.com.gs3.formalistics.model.communicators.HttpCommunicator;
import ph.com.gs3.formalistics.model.communicators.UserCommunicatorModule;
import ph.com.gs3.formalistics.model.communicators.HttpCommunicatorModule.CommunicatorException;
import ph.com.gs3.formalistics.model.valueobjects.application.APIResponse;
import ph.com.gs3.formalistics.model.valueobjects.application.APIResponse.APIInvalidResponseException;
import ph.com.gs3.formalistics.model.valueobjects.business.User;
import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;

public class GetOnlineUsersService extends IntentService {

	public static final String TAG = GetOnlineUsersService.class.getSimpleName();
	public static final String NAME = GetOnlineUsersService.class.getName();

	public static final String EXTRA_CURRENT_USER = "current_user";
	public static final String EXTRA_ONLINE_USERS = "online_users";
	public static final String EXTRA_ERROR_EXCEPTION = "error_exception";

	public static final String ACTION_ON_ERROR = NAME + "_on_error";
	public static final String ACTION_ON_ONLINE_USERS_UDPATED = NAME + "_on_online_users_updated";

	private UserCommunicatorModule userCommunicatorModule;
	private User currentUser;

	public GetOnlineUsersService() {
		super(TAG);
	}

	@Override
	protected void onHandleIntent(Intent intent) {

		initializeFields(intent);
		initializeCommunicator();

		try {

			FLLogger.d(TAG, "Service started");

			APIResponse response = userCommunicatorModule.getOnlineUsers();
			if (response.isOperationSuccessful()) {

				List<User> onlineUsers = new ArrayList<>();

				// throws JSONException
				JSONArray resultsJSON = new JSONArray(response.getResults());
				for (int i = 0; i < resultsJSON.length(); i++) {
					User onlineUser = userJSONToUser(resultsJSON.getJSONObject(i));
					onlineUsers.add(onlineUser);

					FLLogger.d(TAG, "Fetched online user: " + onlineUser.getDisplayName());
				}

				broadcastOnOnlineUsersUpdated(onlineUsers);

			} else {
				Exception e = new Exception(response.getErrorMessage());
				broadcastError(e);
			}
		} catch (CommunicatorException | APIInvalidResponseException | JSONException e) {
			e.printStackTrace();
			broadcastError(e);
		}

	}

	private void initializeFields(Intent intent) {

		Bundle extras = intent.getExtras();
		currentUser = (User) extras.getSerializable(EXTRA_CURRENT_USER);

	}

	private void initializeCommunicator() {

		String server = currentUser.getAccountServer();
		HttpCommunicator communicator = new HttpCommunicator();
		userCommunicatorModule = new UserCommunicatorModule(communicator, server);

	}

	private User userJSONToUser(JSONObject userJSON) throws JSONException {

		User user = new User();

		// values inherited from current user
		user.setAccountServer(currentUser.getAccountServer());
		user.setCompanyId(currentUser.getCompanyId());
		user.setCompanyName(currentUser.getCompanyId());

		// values from the web
		user.setWebId(userJSON.getInt("id"));
		user.setDisplayName(userJSON.getString("displayName"));
		user.setEmail(userJSON.getString("email"));
		user.setUserLevel(userJSON.getInt("user_level_id"));
		user.setImageURL(userJSON.getString("imageURL"));

		return user;

	}

	// ========================================================================
	// {{ Broadcaster Methods

	public void broadcastError(Exception e) {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(ACTION_ON_ERROR);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		broadcastIntent.putExtra(EXTRA_ERROR_EXCEPTION, e);

		sendBroadcast(broadcastIntent);

	}

	public void broadcastOnOnlineUsersUpdated(List<User> users) {

		Intent broadcastIntent = new Intent();
		broadcastIntent.setAction(ACTION_ON_ONLINE_USERS_UDPATED);
		broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);
		broadcastIntent.putExtra(EXTRA_ONLINE_USERS, (ArrayList<User>) users);

		sendBroadcast(broadcastIntent);

	}

	// }}

}
